<template>
  <div class="box">
    <div class="menu-box">
      <Menu @add="addComponent" @preview="$emit('preview')" /><!-- 组件栏 -->
    </div>
    <div class="resize-layout">
      <div class="resize-left" ref="left"
        ><!-- 中间区域 -->
        <div class="content-box" v-if="data.list.length > 0" :key="data.renderKey">
          <grid-layout
            v-model:layout="data.list"
            :col-num="12"
            :row-height="30"
            :is-draggable="true"
            :is-resizable="true"
            :is-mirrored="false"
            :vertical-compact="true"
            :margin="[10, 10]"
            :use-css-transforms="true"
          >
            <grid-item
              v-for="(item, index) in data.list"
              :x="item.x"
              :y="item.y"
              :w="item.w"
              :h="item.h"
              :i="item.i"
              :key="item.i"
              :maxH="item.maxH"
              :minH="item.minH"
              :maxW="item.maxW"
              :minW="item.minW"
              :class="{ 'active-item': item.i === currentId && !data.isGenerateThumb }"
              @click="changeSelect(index)"
            >
              <component
                :id="item.i"
                :w="item.w"
                :h="item.h"
                :type="item.type"
                v-model:config="item.config"
                :title="item.config.title"
                class="item-box"
                :is="getLegendComponent(item.type)"
              />
              <div class="mask">
                <div class="button-list" v-if="item.i === currentId && !data.isGenerateThumb">
                  <a-button shape="circle" size="small" class="clone-button">
                    <Icon
                      icon="ant-design:copy-outlined"
                      class="action-clone"
                      @click.stop="copyComponent(index)"
                    />
                  </a-button>
                  <a-button shape="circle" size="small" danger class="delete-button">
                    <Icon
                      icon="ant-design:delete-outlined"
                      class="action-delete"
                      @click.stop="removeComponent(index)"
                    />
                  </a-button>
                </div>
              </div>
            </grid-item>
          </grid-layout>
        </div>
        <div v-if="data.list.length == 0" class="empty-box">
          <DesktopDesignEmpty class="empty" />
        </div>
      </div>
      <div class="resize-right" ref="right">
        <div class="right-box" v-if="data.list.length > 0">
          <!-- 属性 -->
          <div v-for="(item, index) in data.list" :key="index">
            <component
              v-show="data.currentComponentIndex == index"
              :is="getComponentProperties(item.type)"
              :info="item"
            />
          </div>
        </div>
      </div>
    </div>
    <Title :title="propertiesTitle" class="fewer-panel-box" />
  </div>
</template>

<script setup lang="ts">
  import { computed, nextTick, onMounted, onUnmounted, reactive, ref } from 'vue';
  import html2canvas from 'html2canvas';
  import Menu from './Menu.vue';
  import Title from './Title.vue';
  import { Icon } from '/@/components/Icon';
  import { DesktopInfoItem } from '/@/model/desktop/designer';
  import { DesktopDesignEmpty } from '/@/components/ModalPanel';
  import { DesktopComponent } from '/@/enums/desktop';
  import { cloneDeep } from 'lodash-es';
  import { defaultInfo, InfoByType } from './config/info';
  import { componentTitleFromType } from './config/components';
  import { dataURLtoBlob } from '/@/utils/file/base64Conver';
  import { uploadBlobApi } from '/@/api/sys/upload';
  import useComponentByType from '../../hooks/useComponentByType';
  let left = ref();
  let right = ref();
  let showPanel = ref(false);
  defineEmits(['preview']);
  const props = withDefaults(
    defineProps<{
      list: Array<DesktopInfoItem>;
    }>(),
    {
      list: () => {
        return [];
      },
    },
  );
  const { componentByType } = useComponentByType();
  const data: {
    currentComponentIndex: number;
    renderKey: number;
    list: Array<DesktopInfoItem>;
    showPreview: boolean;
    isGenerateThumb: boolean;
  } = reactive({
    currentComponentIndex: -1,
    list: [],
    renderKey: 0,
    showPreview: false,
    isGenerateThumb: false,
  });
  const currentId = computed(() => {
    return data.list.length > 0 ? data.list[data.currentComponentIndex].i : 0;
  });
  const currentInfo = computed(() => {
    return data.list.length > 0 ? data.list[data.currentComponentIndex] : null;
  });
  const propertiesTitle = computed(() => {
    return showPanel.value && currentInfo.value
      ? componentTitleFromType.get(currentInfo.value.type)
      : null;
  });
  // const showProperties = computed(() => {
  //   return showPanel.value && currentInfo.value ? true : false;
  // });

  onMounted(() => {
    initDisplay();
    window.addEventListener('resize', () => {
      resetDisplay();
    });
  });
  onUnmounted(() => {
    window.removeEventListener('resize', () => {
      resetDisplay();
    });
  });
  function initDisplay() {
    data.list = [];
    if (props.list && props.list.length > 0) {
      data.list = props.list;
      data.currentComponentIndex = 0;
      // showPropertiesBox();
    }
  }
  function getNewY() {
    let newY = 0;
    let height = 0;
    if (data.list.length > 0) {
      let arrFromX = data.list.filter((ele) => {
        return ele.x === 0;
      });
      if (arrFromX.length > 0) {
        arrFromX.forEach((element) => {
          if (element.y >= newY) {
            newY = element.y;
            height = element.h;
          }
        });
        newY = newY + height;
      }
    }

    return newY;
  }
  function addComponent(type: DesktopComponent) {
    let info: DesktopInfoItem | undefined = defaultInfo;
    if (InfoByType.has(type)) {
      info = InfoByType.get(type);
    }
    if (info) {
      info.x = 0;
      info.y = 0;
      if (data.list.length > 0) {
        info.y = getNewY();
      }
      info.i = Date.now() + '_' + Math.ceil(Math.random() * 99999);
      data.list.push(cloneDeep(info));
      data.currentComponentIndex = data.list.length - 1;
      showPropertiesBox();
    }
  }
  function copyComponent(index: number) {
    let info: DesktopInfoItem = cloneDeep(data.list[index]);
    info.x = 0;
    info.y = getNewY();
    info.i = Date.now() + '_' + Math.ceil(Math.random() * 99999);
    data.list.push(info);
    data.currentComponentIndex = data.list.length - 1;
    showPropertiesBox();
  }
  function showPropertiesBox() {
    if (!showPanel.value) {
      setTimeout(() => {
        showPanel.value = true;
        showRightBox();
      }, 1);
    }
  }
  function removeComponent(index: number) {
    data.currentComponentIndex = 0;
    data.list.splice(index, 1);
    hidePropertiesBox();
  }
  function hidePropertiesBox() {
    if (showPanel.value) {
      setTimeout(() => {
        showPanel.value = false;
        hideRightBox();
      }, 1);
    }
  }
  function changeSelect(index: number) {
    data.currentComponentIndex = index;
    showPropertiesBox();
  }
  function resetDisplay() {
    data.renderKey++;
  }
  function getLegendComponent(type: DesktopComponent) {
    return componentByType.has(type)
      ? componentByType.get(type)?.legend
      : componentByType.get(DesktopComponent.DEFAULT)?.legend;
  }
  // function getPropertiesTitle(type) {
  //   return showPanel.value ? componentTitleFromType.get(type) : null;
  // }
  function getComponentProperties(type) {
    return componentByType.has(type)
      ? componentByType.get(type)?.properties
      : componentByType.get(DesktopComponent.DEFAULT)?.properties;
  }
  function showRightBox() {
    showPanel.value = true;
    left.value.style.width = '75%';
    right.value.style.width = '25%';
    resetDisplay();
  }
  function hideRightBox() {
    showPanel.value = false;
    left.value.style.width = '100%';
    right.value.style.width = '0';
    resetDisplay();
  }
  function getDesignData() {
    return data.list;
  }
  async function saveDesignData(isGetUrl = true) {
    if (isGetUrl) {
      data.isGenerateThumb = true;
      await nextTick();
      let thumb = await generateThumb();
      let backgroundUrl = await uploadSign(thumb);
      return { list: data.list, backgroundUrl };
    } else {
      return data.list;
    }
  }
  async function uploadSign(base64) {
    try {
      const blob = dataURLtoBlob(base64);
      const fileUrl = await uploadBlobApi(blob, 'thumb.png');
      return fileUrl;
    } catch (error) {
      return '';
    }
  }
  async function generateThumb() {
    try {
      let canvas = await html2canvas(left.value, {
        backgroundColor: '#f5f5f5',
        useCORS: true,
        windowHeight: document.body.scrollHeight,
      });
      return canvas.toDataURL();
    } catch (error) {
      return '';
    }
  }
  defineExpose({
    saveDesignData,
    getDesignData,
  });
</script>

<style lang="less" scoped>
  .box {
    position: relative;
    width: 100%;
    height: 100%;
  }

  .menu-box {
    width: 48px;
    height: 100%;
    background-color: #fff;
    position: absolute;
    left: 0;
  }

  .resize-layout {
    display: flex;
    height: 100%;
    width: 100%;
  }

  .resize-left {
    width: 100%;
    padding: 0;
    overflow: hidden;
  }

  .resize-shrink-sidebar {
    cursor: col-resize;
    display: flex;
    justify-content: center;
    align-items: center;
  }

  .shrink-sidebar-text {
    border-radius: 4px;

    /* color: #fff; */
  }

  .shrink-sidebar:hover {
    color: #666;
  }

  .resize-right {
    width: 0;

    /* 右侧初始化宽度 */
    background-color: #fff;
  }

  .right-box {
    height: 100%;
    margin-right: 10px;
  }

  .fewer-panel-box {
    width: 25%;
    position: fixed;
    top: 60px;
    z-index: 3;
    right: 0;
  }

  .vue-grid-layout {
    // background: #eee;
    height: 100%;
  }

  .content-box {
    height: 100%;
    padding-left: 50px;
    overflow: auto;
    padding-bottom: 60px;
  }

  .button-list {
    position: absolute;
    right: 0;
    top: -10px;
  }

  .action-clone {
    color: @primary-color;
  }

  .clone-button {
    background-color: #eff4ff;
    margin-right: 4px;
  }

  .delete-button {
    background-color: #fce3e8;
    margin-right: 4px;
  }

  .action-delete {
    color: @clear-color;
  }

  .mask {
    position: absolute;
    inset: 0;
    padding: 2px;
  }

  .active-item {
    border: 1px solid #39f;
  }

  .item-box {
    position: relative;
    background-color: #fff;
    width: 100%;
    height: 100%;
    min-width: 10px;
    min-height: 10px;
    box-shadow: 0 3px 6px 1px rgb(0 0 0 / 16%);
    border-radius: 4px;
  }

  .vue-grid-item:hover {
    border: 1px dotted #39f;
  }

  .empty-box {
    width: 100%;
    height: 100%;
    display: flex;
    justify-content: center;
    align-items: center;

    .empty {
      width: 480px;
    }
  }
</style>
